Libraries
Load data
I am using the AHA dataset for writing my code because it is the
simplest dataset I can work with. Simplest = significant number of
baseline samples without issue of repeated measures, balanced
distribution of classes, likely difference to be detected present.
a_ps = readRDS("/Users/aa370/Library/CloudStorage/Box-Box/project_davidlab/LAD_LAB_Personnel/Ammara_A/Projects/AHA/220714_MN00462_0226_A000H3WKM5/20221110_results/ps_objects/AHA_trnl_with_metadata_20221205.rds")
a_ps
phyloseq-class experiment-level object
otu_table() OTU Table: [ 235 taxa and 95 samples ]
sample_data() Sample Data: [ 95 samples by 33 sample variables ]
tax_table() Taxonomy Table: [ 235 taxa by 10 taxonomic ranks ]
c_ps = readRDS("/Users/aa370/Library/CloudStorage/Box-Box/project_davidlab/LAD_LAB_Personnel/Ammara_A/Projects/CHOICE/CHOICE_Trnl/CHOICE_20220912/ps_objects/choice_complete_20221205_clean.rds")
c_ps
phyloseq-class experiment-level object
otu_table() OTU Table: [ 571 taxa and 171 samples ]
sample_data() Sample Data: [ 171 samples by 30 sample variables ]
tax_table() Taxonomy Table: [ 571 taxa by 10 taxonomic ranks ]
Preprocess
Remove problematic samples
Taking out samples that are not listed to have completed the study
and samples with more than 0 reads reduces samples from 95 down to
77.
Taking only the baseline timepoint brings further down to 44
samples
Keeping non-completed samples reduced the AUC of modelling
substantially, remove these samples as before.
a_ps = a_ps %>%
subset_samples(completion == "Completed" & reads >0) %>%
subset_samples(timepoint == "Baseline")
a_ps
phyloseq-class experiment-level object
otu_table() OTU Table: [ 235 taxa and 44 samples ]
sample_data() Sample Data: [ 44 samples by 33 sample variables ]
tax_table() Taxonomy Table: [ 235 taxa by 10 taxonomic ranks ]
Class distribution in this dataset: Case = 20 Control = 24
sample_data(a_ps) %>%
as.data.frame() %>%
as_tibble() %>%
group_by(group) %>%
summarise(count = n())
Remove unassigned taxa
Debating whether this should be done for machine learning. Because we
are simply throwing out because we don’t know what there are and even if
they account for a small percentage of reads, they might still have
important information.
I think I will refrain from removing unless I have a good reason
to.
Don’t do this because some very important taxa for ML model turned
out to be unassigned. - 12/8/22
Removing completely unassigned taxa reduces taxa from 235 to 82.
a_ps = a_ps %>%
subset_taxa(is.na(superkingdom) == FALSE)
a_ps
phyloseq-class experiment-level object
otu_table() OTU Table: [ 82 taxa and 44 samples ]
sample_data() Sample Data: [ 44 samples by 33 sample variables ]
tax_table() Taxonomy Table: [ 82 taxa by 10 taxonomic ranks ]
Merge phyloseq
combined = merge_phyloseq(c_ps, a_ps)
combined
phyloseq-class experiment-level object
otu_table() OTU Table: [ 674 taxa and 215 samples ]
sample_data() Sample Data: [ 215 samples by 41 sample variables ]
tax_table() Taxonomy Table: [ 674 taxa by 10 taxonomic ranks ]
Aligning seq table
seqtab = combined@otu_table
seqtab_merged = dada2::collapseNoMismatch(seqtab)
combined = phyloseq(otu_table(seqtab_merged, taxa_are_rows=FALSE),
sample_data(combined@sam_data),
tax_table(combined@tax_table))
combined
phyloseq-class experiment-level object
otu_table() OTU Table: [ 660 taxa and 215 samples ]
sample_data() Sample Data: [ 215 samples by 41 sample variables ]
tax_table() Taxonomy Table: [ 660 taxa by 10 taxonomic ranks ]
sample_data(combined)
Sample Data: [215 samples by 41 sample variables]:
Feature table
Zero variance features
No features have zero variance
nzv = features %>%
select(!sample) %>%
nearZeroVar(saveMetrics = TRUE)
nzv %>%
filter(nzv == TRUE)
rm(nzv)
Modeling
Loop
auc_list
[1] 0.75 0.25 0.50 0.44 0.69 0.69 0.75 0.75 0.56 0.56 0.88 0.81 0.94
[14] 0.62 0.62 0.88 0.50 0.62 0.50 0.94
Plotting
AUC plot and t-test

Save external predictions
predictions
save = cummulative_external %>%
#filter(auc == max) %>%
left_join(samdf) %>%
arrange(iteration, treatment, id, true_week)
Joining, by = "sample"
variable importances
LS0tCnRpdGxlOiAiUiBOb3RlYm9vayIKb3V0cHV0OiBodG1sX25vdGVib29rCi0tLQoKIyBMaWJyYXJpZXMKCmBgYHtyLCBpbmNsdWRlID0gRkFMU0V9CmxpYnJhcnkodGlkeXZlcnNlKQpsaWJyYXJ5KG1pY3JvYmlvbWUpCmxpYnJhcnkocGh5bG9zZXEpCmxpYnJhcnkoY2FyZXQpCmxpYnJhcnkocmFuZG9tRm9yZXN0KQpsaWJyYXJ5KE1CdXRpbHMpCmBgYAoKIyBMb2FkIGRhdGEKCkkgYW0gdXNpbmcgdGhlIEFIQSBkYXRhc2V0IGZvciB3cml0aW5nIG15IGNvZGUgYmVjYXVzZSBpdCBpcyB0aGUgc2ltcGxlc3QgZGF0YXNldCBJIGNhbiB3b3JrIHdpdGguClNpbXBsZXN0ID0gc2lnbmlmaWNhbnQgbnVtYmVyIG9mIGJhc2VsaW5lIHNhbXBsZXMgd2l0aG91dCBpc3N1ZSBvZiByZXBlYXRlZCBtZWFzdXJlcywgYmFsYW5jZWQgZGlzdHJpYnV0aW9uIG9mIGNsYXNzZXMsIGxpa2VseSBkaWZmZXJlbmNlIHRvIGJlIGRldGVjdGVkIHByZXNlbnQuCgoKYGBge3J9CmFfcHMgPSByZWFkUkRTKCIvVXNlcnMvYWEzNzAvTGlicmFyeS9DbG91ZFN0b3JhZ2UvQm94LUJveC9wcm9qZWN0X2RhdmlkbGFiL0xBRF9MQUJfUGVyc29ubmVsL0FtbWFyYV9BL1Byb2plY3RzL0FIQS8yMjA3MTRfTU4wMDQ2Ml8wMjI2X0EwMDBIM1dLTTUvMjAyMjExMTBfcmVzdWx0cy9wc19vYmplY3RzL0FIQV90cm5sX3dpdGhfbWV0YWRhdGFfMjAyMjEyMDUucmRzIikKCmFfcHMKYGBgCgpgYGB7cn0KY19wcyA9IHJlYWRSRFMoIi9Vc2Vycy9hYTM3MC9MaWJyYXJ5L0Nsb3VkU3RvcmFnZS9Cb3gtQm94L3Byb2plY3RfZGF2aWRsYWIvTEFEX0xBQl9QZXJzb25uZWwvQW1tYXJhX0EvUHJvamVjdHMvQ0hPSUNFL0NIT0lDRV9Ucm5sL0NIT0lDRV8yMDIyMDkxMi9wc19vYmplY3RzL2Nob2ljZV9jb21wbGV0ZV8yMDIyMTIwNV9jbGVhbi5yZHMiKQoKY19wcwpgYGAKCiMgUHJlcHJvY2VzcwoKIyMgUmVtb3ZlIHByb2JsZW1hdGljIHNhbXBsZXMKClRha2luZyBvdXQgc2FtcGxlcyB0aGF0IGFyZSBub3QgbGlzdGVkIHRvIGhhdmUgY29tcGxldGVkIHRoZSBzdHVkeSBhbmQgc2FtcGxlcyB3aXRoIG1vcmUgdGhhbiAwIHJlYWRzIHJlZHVjZXMgc2FtcGxlcyBmcm9tIDk1IGRvd24gdG8gNzcuCgpUYWtpbmcgb25seSB0aGUgYmFzZWxpbmUgdGltZXBvaW50IGJyaW5ncyBmdXJ0aGVyIGRvd24gdG8gNDQgc2FtcGxlcwoKS2VlcGluZyBub24tY29tcGxldGVkIHNhbXBsZXMgcmVkdWNlZCB0aGUgQVVDIG9mIG1vZGVsbGluZyBzdWJzdGFudGlhbGx5LCByZW1vdmUgdGhlc2Ugc2FtcGxlcyBhcyBiZWZvcmUuCgpgYGB7cn0KYV9wcyA9IGFfcHMgJT4lCiAgc3Vic2V0X3NhbXBsZXMoY29tcGxldGlvbiA9PSAiQ29tcGxldGVkIiAmIHJlYWRzID4wKSAlPiUKICBzdWJzZXRfc2FtcGxlcyh0aW1lcG9pbnQgPT0gIkJhc2VsaW5lIikKCmFfcHMKCmBgYAoKQ2xhc3MgZGlzdHJpYnV0aW9uIGluIHRoaXMgZGF0YXNldDoKQ2FzZSA9IDIwCkNvbnRyb2wgPSAyNAoKYGBge3J9CnNhbXBsZV9kYXRhKGFfcHMpICU+JQogIGFzLmRhdGEuZnJhbWUoKSAlPiUKICBhc190aWJibGUoKSAlPiUKICBncm91cF9ieShncm91cCkgJT4lCiAgc3VtbWFyaXNlKGNvdW50ID0gbigpKQpgYGAKIyMgUmVtb3ZlIHVuYXNzaWduZWQgdGF4YQoKRGViYXRpbmcgd2hldGhlciB0aGlzIHNob3VsZCBiZSBkb25lIGZvciBtYWNoaW5lIGxlYXJuaW5nLiBCZWNhdXNlIHdlIGFyZSBzaW1wbHkgdGhyb3dpbmcgb3V0IGJlY2F1c2Ugd2UgZG9uJ3Qga25vdyB3aGF0IHRoZXJlIGFyZSBhbmQgZXZlbiBpZiB0aGV5IGFjY291bnQgZm9yIGEgc21hbGwgcGVyY2VudGFnZSBvZiByZWFkcywgdGhleSBtaWdodCBzdGlsbCBoYXZlIGltcG9ydGFudCBpbmZvcm1hdGlvbi4KCkkgdGhpbmsgSSB3aWxsIHJlZnJhaW4gZnJvbSByZW1vdmluZyB1bmxlc3MgSSBoYXZlIGEgZ29vZCByZWFzb24gdG8uCgpEb24ndCBkbyB0aGlzIGJlY2F1c2Ugc29tZSB2ZXJ5IGltcG9ydGFudCB0YXhhIGZvciBNTCBtb2RlbCB0dXJuZWQgb3V0IHRvIGJlIHVuYXNzaWduZWQuIC0gMTIvOC8yMgoKUmVtb3ZpbmcgY29tcGxldGVseSB1bmFzc2lnbmVkIHRheGEgcmVkdWNlcyB0YXhhIGZyb20gMjM1IHRvIDgyLgoKYGBge3J9CiMgYV9wcyA9IGFfcHMgJT4lCiMgICBzdWJzZXRfdGF4YShpcy5uYShzdXBlcmtpbmdkb20pID09IEZBTFNFKQojIAojIGFfcHMKYGBgCgojIyBNZXJnZSBwaHlsb3NlcQoKYGBge3J9CmNvbWJpbmVkID0gbWVyZ2VfcGh5bG9zZXEoY19wcywgYV9wcykKCmNvbWJpbmVkCmBgYAoKIyMjIEFsaWduaW5nIHNlcSB0YWJsZQoKYGBge3J9CnNlcXRhYiA9IGNvbWJpbmVkQG90dV90YWJsZQoKc2VxdGFiX21lcmdlZCA9IGRhZGEyOjpjb2xsYXBzZU5vTWlzbWF0Y2goc2VxdGFiKQoKY29tYmluZWQgPSBwaHlsb3NlcShvdHVfdGFibGUoc2VxdGFiX21lcmdlZCwgdGF4YV9hcmVfcm93cz1GQUxTRSksCiAgICAgICAgICAgICAgIHNhbXBsZV9kYXRhKGNvbWJpbmVkQHNhbV9kYXRhKSwgCiAgICAgICAgICAgICAgIHRheF90YWJsZShjb21iaW5lZEB0YXhfdGFibGUpKQoKY29tYmluZWQKCiNzYW1wbGVfZGF0YShjb21iaW5lZCkKYGBgCgojIyBEYXRhIHRyYW5zZm9ybQoKYGBge3J9Cm90dV9jbHIgPSBhYnVuZGFuY2VzKGNvbWJpbmVkLCAiY2xyIikgJT4lIAogIHQoKQoKY29tYmluZWQgPSBwaHlsb3NlcShvdHVfdGFibGUob3R1X2NsciwgdGF4YV9hcmVfcm93cyA9IEZBTFNFKSwKICAgICAgICAgICAgICAgICAgIHNhbXBsZV9kYXRhKGNvbWJpbmVkQHNhbV9kYXRhKSwKICAgICAgICAgICAgICAgICAgIHRheF90YWJsZShjb21iaW5lZEB0YXhfdGFibGUpKQoKcm0ob3R1X2NscikKYGBgCgojIyBGZWF0dXJlIHRhYmxlCgojIyMgRXh0cmFjdCBkYXRhCgpPcmRlciBvZiBhc3YgY29sbmFtZXMgaW4gT1RVIHRhYmxlIGFuZCB0YXggdGFibGUgaXMgdGhlIHNhbWUuCmBgYHtyfQpmZWF0dXJlcyA9IGNvbWJpbmVkQG90dV90YWJsZSAlPiUKICBhcy5kYXRhLmZyYW1lKCkgJT4lCiAgYXNfdGliYmxlKHJvd25hbWVzID0gTkEpICU+JQogIHJvd25hbWVzX3RvX2NvbHVtbigic2FtcGxlIikKCmZlYXR1cmVfbGFiZWxzID0gYygic2FtcGxlIikKCmZlYXR1cmVzCmBgYAojIyMgWmVybyB2YXJpYW5jZSBmZWF0dXJlcwoKTm8gZmVhdHVyZXMgaGF2ZSB6ZXJvIHZhcmlhbmNlCmBgYHtyfQpuenYgPSBmZWF0dXJlcyAlPiUKICBzZWxlY3QoIXNhbXBsZSkgJT4lCiAgbmVhclplcm9WYXIoc2F2ZU1ldHJpY3MgPSBUUlVFKQpgYGAKCmBgYHtyfQpuenYgJT4lCiAgZmlsdGVyKG56diA9PSBUUlVFKQpgYGAKCgpgYGB7cn0Kcm0obnp2KQpgYGAKCiMjIyBDb3JyZWxhdGVkIHByZWRpY3RvcnMKCmBgYHtyfQpmZWF0dXJlX2NvciA9IGZlYXR1cmVzICU+JQogc2VsZWN0KCFzYW1wbGUpICU+JQogY29yKCkgCgpzdW1tYXJ5KGZlYXR1cmVfY29yW3VwcGVyLnRyaShmZWF0dXJlX2NvcildKQpgYGAKCmBgYHtyfQpoaWdoX2NvciA9IGZpbmRDb3JyZWxhdGlvbihmZWF0dXJlX2NvciwgY3V0b2ZmID0gLjUwKSAjdXNpbmcgYSBtb3JlIHBlcm1pc3NpdmUgY3V0b2ZmIGJlY2F1c2UgYSBsb3Qgb2YgY29sdW1ucyBzdGlsbCBsZWZ0IGluIHRoZSBpbnB1dCB0YWJsZQoKZmlsdGVyZWRfZmVhdHVyZXMgPSBmZWF0dXJlc1ssLWhpZ2hfY29yXQpgYGAKCmBgYHtyfQpybShoaWdoX2NvcikKcm0oZmVhdHVyZV9jb3IpCmBgYAoKIyMjIExpbmVhciBkZXBlbmRlbmNpZXMKCmBgYHtyfQpmZWF0dXJlX2xkID0gZmlsdGVyZWRfZmVhdHVyZXMgJT4lCiAgc2VsZWN0KCFzYW1wbGUpICU+JQogIGZpbmRMaW5lYXJDb21ib3MoKQoKZmlsdGVyZWRfZmVhdHVyZXMgPSBmaWx0ZXJlZF9mZWF0dXJlc1ssIC0gZmVhdHVyZV9sZCRyZW1vdmVdCmBgYAoKIyMgSW5wdXQgdGFibGUKYGBge3J9CnNhbXBsZV9sYWJlbHMgPSBjb21iaW5lZEBzYW1fZGF0YSU+JQogIGFzLmRhdGEuZnJhbWUoKSAlPiUKICBhc190aWJibGUocm93bmFtZXMgPSBOQSkgJT4lCiAgcm93bmFtZXNfdG9fY29sdW1uKCJzYW1wbGUiKSAlPiUKICBzZWxlY3Qoc2FtcGxlLCBncm91cCkgJT4lCiAgbGVmdF9qb2luKGZpbHRlcmVkX2ZlYXR1cmVzKQoKaW5wdXQgPSBzYW1wbGVfbGFiZWxzICU+JQogIGZpbHRlcihzdHJfZGV0ZWN0KHNhbXBsZSwgIkFIQSIpKSAlPiUKICBtdXRhdGUoZ3JvdXBfc2h1ZmZsZSA9IHNhbXBsZShncm91cCkpCgpleHRlcm5hbF90ZXN0ID0gc2FtcGxlX2xhYmVscyAlPiUKICBmaWx0ZXIoIXN0cl9kZXRlY3Qoc2FtcGxlLCAiQUhBIikpICU+JQogIHNlbGVjdCgtYyhncm91cCkpCmBgYAoKIyBNb2RlbGluZwoKIyMgQmFzZWxpbmUgcGVyZm9ybWFuY2UKCmBgYHtyfQpsYWJlbF9saXN0ID0gYygiZ3JvdXAiLCAiZ3JvdXBfc2h1ZmZsZSIpCnJlc3VsdHMgPSBsb29wX2xhYmVsKGl0ZXJhdGlvbnMgPSAyMCwgaW5wdXQsIGxhYmVsX2xpc3QsIHBlcmNlbnQgPSAwLjgpCgphdWNfZGYgPSByZXN1bHRzW1syXV0KCmltcG9ydGFuY2VfZGYgPSByZXN1bHRzW1sxXV0KYGBgCgojIyBMb29wCgpgYGB7cn0KbGFiZWwgPSAiZ3JvdXAiCgppbXBvcnRhbmNlX2RmID0gZGF0YS5mcmFtZSgpCgpjdW1tdWxhdGl2ZV9leHRlcm5hbCA9IGRhdGEuZnJhbWUoKQoKYXVjX2xpc3QgPSBjKCkKCmN1cnJlbnRfZGF0YSA9IGlucHV0ICU+JQogICAgICBzZWxlY3QoLWxhYmVsX2xpc3RbbGFiZWxfbGlzdCAhPSBsYWJlbF0pICU+JQogICAgICBzZWxlY3QoLXNhbXBsZSkKCmZvcihpIGluIDE6MjApIHsKICAjIERhdGEgc3BsaXR0aW5nCiAgICB0cmFpbl9pbmQgPSBjYXJldDo6Y3JlYXRlRGF0YVBhcnRpdGlvbigoY3VycmVudF9kYXRhICU+JQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcHVsbChsYWJlbCkpLCAjc3BsaXQgYmFzZWQgb24gbGFiZWwgY29sdW1uCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwID0gMC44LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGlzdCA9IEZBTFNFLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGltZXMgPSAxKQogICAgdHJhaW4gPSBjdXJyZW50X2RhdGFbdHJhaW5faW5kLF0KICAgIHRlc3QgPSBjdXJyZW50X2RhdGFbLXRyYWluX2luZCxdCiAgICAKICAgICMgVHJhaW5pbmcgbW9kZWwKICAgIAogICAgZm9ybXVsYSA9IGxhYmVsICU+JQogICAgICBwYXN0ZTAoIn4uIikgJT4lCiAgICAgIGFzLmZvcm11bGEoKQogICAgCiAgICBmaXRfY29udHJvbCA9IGNhcmV0Ojp0cmFpbkNvbnRyb2wobWV0aG9kID0gIkNWIiwgIyA1LWZvbGQgY3Jvc3MgdmFsaWRhdGlvbgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBudW1iZXIgPSA1LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdW1tYXJ5RnVuY3Rpb24gPSBwclN1bW1hcnksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNsYXNzUHJvYnMgPSBUKQogICAgCiAgICBtb2RlbCA9IGNhcmV0Ojp0cmFpbihmb3JtdWxhLCAjdXNpbmcgZm9ybXVsYSBzcGVjaWZpZWQgCiAgICAgICAgICAgICAgZGF0YSA9IHRyYWluLAogICAgICAgICAgICAgICAgICBtZXRob2QgPSAicmYiLAogICAgICAgICAgICAgICAgICB0ckNvbnRyb2wgPSBmaXRfY29udHJvbCwKICAgICAgICAgICAgICAgICAgdmVyYm9zZSA9IEZBTFNFLCAKICAgICAgICAgICAgICAgICAgbWV0cmljID0gIkFVQyIpCiAgICAKICAgICMgTW9kZWwgcHJlZGljdGlvbnMKICAgIAogICAgcHJlZGljdGlvbnMgPSBwcmVkaWN0KG1vZGVsLCBuZXdkYXRhID0gdGVzdCwgdHlwZT0gInByb2IiKQogICAgCiAgICBwcmVkaWN0aW9ucyRvYnMgPSB0ZXN0ICU+JQogICAgICBwdWxsKGxhYmVsKSAlPiUKICAgICAgYXMuZmFjdG9yKCkgCiAgICAKICAgICMgRXZhbHVhdGUgbW9kZWwKICAgIAogICAgZXZhbCA9IE1MZXZhbDo6ZXZhbG0ocHJlZGljdGlvbnMsIHNob3dwbG90cyA9IEZBTFNFLCBzaWxlbnQgPSBUUlVFKQogICAgCiAgICBhdWMgPSBldmFsJHN0ZHJlcyRgR3JvdXAxYFsxMywxXQogICAgCiAgICBhdWNfbGlzdCA9IGFwcGVuZChhdWNfbGlzdCwgYXVjKQogICAgCiAgICAjRXh0cmFjdCBmZWF0dXJlIGltcG9ydGFuY2UKCiAgICBmZWF0dXJlX2ltcG9ydGFuY2UgPSBjYXJldDo6dmFySW1wKG1vZGVsJGZpbmFsTW9kZWwpICU+JSAjIEJlbiBjYWxscyB0aGlzIGltcG9ydGFuY2VzIGluc3RlYWQgb2YgZmluYWwgbW9kZWwgYnV0IHRoZSByYW5raW5ncyBhcmUgZXhhY3RseSB0aGUgc2FtZSwgb25seSBudW1iZXIgdmFsdWUgc2NhbGUgaXMgZGlmZmVyZW50LgogICAgICBhcnJhbmdlKGRlc2MoT3ZlcmFsbCkpICU+JQogICAgICBhcy5tYXRyaXgoKSAlPiUKICAgICAgdCgpICU+JQogICAgICBhcy5kYXRhLmZyYW1lKCkKICAgIAogICAgZmVhdHVyZV9pbXBvcnRhbmNlJGF1YyA9IGF1YwogICAgCiAgICBmZWF0dXJlX2ltcG9ydGFuY2UkaXRlcmF0aW9uID0gaQogICAgCiAgICBmZWF0dXJlX2ltcG9ydGFuY2UkbGFiZWwgPSBsYWJlbAogICAgCiAgICBpbXBvcnRhbmNlX2RmID0gcmJpbmQoaW1wb3J0YW5jZV9kZiwgZmVhdHVyZV9pbXBvcnRhbmNlKQogICAgCiAgICAjUHJlZGljdGluZyBvbiBleHRlcm5hbCBkYXRhc2V0CiAgICAKICAgIGV4dGVybmFsX3ByZWRpY3Rpb25zID0gIHByZWRpY3QobW9kZWwsIG5ld2RhdGEgPSBleHRlcm5hbF90ZXN0LCB0eXBlPSAicHJvYiIpCiAgICAKICAgIGV4dGVybmFsX3ByZWRpY3Rpb25zJHNhbXBsZSA9IGV4dGVybmFsX3Rlc3Qkc2FtcGxlCiAgICAKICAgIGV4dGVybmFsX3ByZWRpY3Rpb25zJGF1YyA9IGF1YwogICAgCiAgICBleHRlcm5hbF9wcmVkaWN0aW9ucyRwcmVkID0gcHJlZGljdChtb2RlbCwgbmV3ZGF0YSA9IGV4dGVybmFsX3Rlc3QpJT4lCiAgICAgIGFzLmZhY3RvciAoKQogICAgCiAgICBleHRlcm5hbF9wcmVkaWN0aW9ucyRpdGVyYXRpb24gPSBpCiAgICAKICAgIGN1bW11bGF0aXZlX2V4dGVybmFsID0gcmJpbmQoY3VtbXVsYXRpdmVfZXh0ZXJuYWwsIGV4dGVybmFsX3ByZWRpY3Rpb25zKQogICAgCn0KCmF1Y19saXN0CgppbXBvcnRhbmNlX2RmCgpjdW1tdWxhdGl2ZV9leHRlcm5hbCAgCiAgCmBgYAoKIyBQbG90dGluZwoKIyMgQVVDIHBsb3QgYW5kIHQtdGVzdApgYGB7cn0KZGF0YS5mcmFtZShhdWMgPSBhdWNfbGlzdCklPiUKICBnZ3Bsb3QoKSsKICBnZW9tX2JveHBsb3QoYWVzKHkgPSBhdWMpKSsKICB0aGVtZV9jbGFzc2ljKCkKYGBgCgojIyBTYXZlIGV4dGVybmFsIHByZWRpY3Rpb25zCgojIyMgcHJlZGljdGlvbnMKYGBge3J9Cm1heCA9IG1heChhdWNfbGlzdCkKCnNhbWRmID0gY19wc0BzYW1fZGF0YSU+JQogIGFzLmRhdGEuZnJhbWUoKSAlPiUKICBhc190aWJibGUocm93bmFtZXMgPSBOQSkgJT4lCiAgcm93bmFtZXNfdG9fY29sdW1uKCJzYW1wbGUiKSAlPiUKICBzZWxlY3Qoc2FtcGxlLCBpZCwgdHJlYXRtZW50LCB0cnVlX3dlZWssIHRpbWVwb2ludCkgCgpzYXZlID0gY3VtbXVsYXRpdmVfZXh0ZXJuYWwgJT4lCiAgI2ZpbHRlcihhdWMgPT0gbWF4KSAlPiUKICBsZWZ0X2pvaW4oc2FtZGYpICU+JQogIGFycmFuZ2UoaXRlcmF0aW9uLCB0cmVhdG1lbnQsIGlkLCB0cnVlX3dlZWspCmBgYAoKYGBge3J9CndyaXRlX2NzdihzYXZlLCAiL1VzZXJzL2FhMzcwL0xpYnJhcnkvQ2xvdWRTdG9yYWdlL0JveC1Cb3gvcHJvamVjdF9kYXZpZGxhYi9MQURfTEFCX1BlcnNvbm5lbC9BbW1hcmFfQS9Qcm9qZWN0cy9NYWNoaW5lX2xlYXJuaW5nL0xBRF9sYWJfTUwvY29kZS9haGFfdG9fY2hvaWNlX3ByZWRpY3Rpb25zLmNzdiIpCmBgYAoKCiMjIyB2YXJpYWJsZSBpbXBvcnRhbmNlcwoKYGBge3J9CndyaXRlX2NzdihpbXBvcnRhbmNlX2RmLCAiL1VzZXJzL2FhMzcwL0xpYnJhcnkvQ2xvdWRTdG9yYWdlL0JveC1Cb3gvcHJvamVjdF9kYXZpZGxhYi9MQURfTEFCX1BlcnNvbm5lbC9BbW1hcmFfQS9Qcm9qZWN0cy9NYWNoaW5lX2xlYXJuaW5nL0xBRF9sYWJfTUwvY29kZS9haGFfdG9fY2hvaWNlX2ZlYXR1cmVfaW1wb3J0YW5jZS5jc3YiKQpgYGAKCgoKCgoK